/**
 * Created by zaranengap on 2017/7/13.
 *
 * 2018/11/26 ZaraNengap
 * For future manager：
 * 本来这里只是个公用方法工具库
 * 不知不觉这里多了很多奇怪的东西
 * 所以，不要想着改变团队
 * 是团队在改变你
 *
 * 我把react，js原型扩展分离
 * 然后需要把这些公共函数用类进行封装
 *
 */
import zh from "share/i18n/zh_CN";
import en from "share/i18n/en_US";
import React from "react";
import moment from "moment";
import configureStore from "stores";
import httpFetch from "share/httpFetch";
import config from "config";
import constants from "share/constants";
import showMenu from "routes/showMenu";
import menuRoute from "routes/menuRoute";
import "share/prototype-extend/react-prototype";
import "share/prototype-extend/js-prototype";
import "share/prototype-extend/window";
import { message, Popover } from "antd";
import round from "lodash/round";

/**
 * 删除数组元素.
 * @param item  被删的元素
 * @return 被删的下标
 */
Array.prototype.delete = function (item) {
  for (let i = 0; i < this.length; i++) {
    if (this[i] === item) {
      this.splice(i, 1);
      return i;
    }
  }
  return -1;
};

/**
 * 后端数据请求，这个最好移除，写个公共service,
 * 得到系统值列表
 * 1001 人员类型
 * 1002 职务
 * 1003 携程子账户
 * 1004 银行名称
 * 1005 国籍
 * 1006 证件类型
 * 1007 性别
 * 1008 员工级别
 * 1010 会计期间名称附加
 * 1013 自定义字段类型名称值列表
 * 2001 版本状态
 * 2002 编制期段
 * 2003 布局位置
 * 2004 预算项目变动属性
 * 2005 预算控制方法
 * 2006 预算控制策略类型
 * 2007 预算控制策略范围
 * 2008 预算控制策略对象
 * 2009 预算控制策略方式
 * 2010 预算控制策略预算符号
 * 2011 控制期段
 * 2012 规则参数类型
 * 2013 取值方式
 * 2014 取值范围
 * 2015 规则参数类型_预算相关
 * 2016 规则参数类型_组织架构相关
 * 2017 规则参数类型_维度相关
 * 2018 预算业务类型
 * 2019 金额／数量
 * 2020 期间汇总标志
 * 2021 预算季度
 * 2022 预算控制消息
 * 2023 单据类别
 * 2024 重置频率
 * 2025 段值
 * 2026 日期格式
 * 2101 汇率方法
 * 2102 汇率标价方法
 * 2103 银行类型
 * 2104 现金交易事务类型
 * 2105 付款方式类型
 * 2106 单据类别
 * 2107 收款方类型
 * 2108 通用待付信息付款状态
 * 2109 付款状态
 * 2110 退款状态
 * 2111 支付日志操作类型
 * 2201 合同状态
 * 2202 合同大类
 * 2205 科目类型
 * 2206 报表类型
 * 2207 余额方向
 * 2208 来源事务
 * 2209 核算场景
 * 2210 核算要素取值方式
 * 2211 核算要素转换规则
 * 2212 交易判断规则
 * 2213 交易核算段取值方式
 * 4001 报表维度-费用类型代码
 * 5002 报销单状态
 * 5003 发票检验结果
 * 5004 驳回节点
 * 5005 发票状态
 * 5006 单据类型
 * 1012 发票类型
 *
 *
 * @param code 值列表代码
 */
React.Component.prototype.getSystemValueList = (code, params) => {
  let url = "";
  if (Number(code) > 2000)
    url = "/api/custom/enumerations/template/by/type?type=";
  else
    url = "/api/custom/enumeration/system/by/type?systemCustomEnumerationType=";
  return httpFetch.get(`${config.baseUrl}${url}${code}`, params).then((res) => {
    return new Promise((resolve) => {
      if (res.data.splice) {
        const result = JSON.parse(JSON.stringify(res));
        result.data = { values: res.data };
        resolve(result);
      } else {
        resolve(res);
      }
    });
  });
};

/**
 * 对象深拷贝
 * @obj obj
 * @return obj
 */
export function deepCopy(obj) {
  //兼容以前
  return deepFullCopy(obj);
}

/**
 * 数组中的对象，以某一个属性稳定排序 默认从小到大,冒泡
 * @arr arr 要排序的数组
 * @property string | number 排序属性，属性值需要能转为数字
 * @return arr 排序好的数组
 */
export function sortByProperty(_arr, property, isReverse) {
  const arr = deepFullCopy(_arr);
  const len = arr.length - 1;
  for (let i = 0; i < len; i++) {
    for (let j = 0; j < len; j++) {
      if (parseFloat(arr[j][property]) > parseFloat(arr[j + 1][property])) {
        const temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
      }
    }
  }
  if (isReverse) {
    return arr.reverse();
  }
  return arr;
}

//判断类型
export function isType(arg) {
  let type = Object.prototype.toString.call(arg);
  type = type.slice(8, type.length - 1).toLowerCase();
  return type;
}

/**
 * 对象深拷贝
 * 不拷贝原型上的属性与方法
 * @obj obj
 * @return obj
 */
export function deepFullCopy(obj, deep = true) {
  if (deep === false) {
    //兼容以前的函数，搞不懂既然是深拷贝，为什么还要这个参数
    return obj;
  }
  return deepClone(obj);

  function find(arr, item) {
    for (let i = 0; i < arr.length; i++) {
      if (arr[i].source === item) {
        return arr[i];
      }
    }
    return null;
  }
  /*
   * 目前只考虑 object array，其他对象都是直接返回,其中 Number Boolean Null Undefined Symbol等基本类型符合期望,
   * 如果要支持 WeakMap WeakSet Map Set Promise Date Regexp Error Function 等对象,
   * 自行根据需要进行扩展，参考 deepCopyArr
   * 为什么？
   * 1.只是对之前的 deepFullCopy 优化，保留之前的 deepFullCopy 功能
   * 2.es6+ 被编译 es5, 加上 polyfill 会减少数据类型，比如 es5 没有 Map，在 es5 中 Map 实例也就是一个对象
   * 3.占时懒得写
   * 多说两句：
   * 请看deepCopyArr，就是在js中，一个一维数组里面，什么数据类型，都可以往里面塞，比如同时存数组\对象\函数\字符串等,
   * 这种场景与语法，随着语言的规范性与团队规范性，这些弊端可以忽略，检测的时候，可以忽略。
   * */
  function isObjectOrArr(obj) {
    const type = isType(obj);
    return type === "object" || type === "array";
  }

  function deepClone(source, uniqueList) {
    if (!isObjectOrArr(source)) {
      return source;
    }

    if (!uniqueList) {
      // 解决循环引用
      uniqueList = [];
    }

    const target = Array.isArray(source) ? [] : {};
    const uniqueData = find(uniqueList, source);
    if (uniqueData) {
      return uniqueData.target;
    }

    //把已经拷贝的数据记录
    uniqueList.push({
      source: source,
      target: target,
    });

    for (const key in source) {
      if (isObjectOrArr(source[key])) {
        target[key] = deepClone(source[key], uniqueList);
      } else {
        target[key] = source[key];
      }
    }
    // 之前有人提议，不拷贝原型
    // 不行，比如那个 moment 对象很多方法就是在原型上
    // Object.keys(source).map(key => {
    //   console.log(source)
    //   console.log(key)
    //   if (isObjectOrArr(source[key])) {
    //     target[key] = deepClone(source[key], uniqueList)
    //   } else {
    //     target[key] = source[key];
    //   }
    // });
    return target;
  }
}

/*
 * @departed
 * 由于 array 与 object 不同的数据类型，使用了同样的拷贝方法，缺少属性判断，会导致期望结果有偏差，重写
 * */
export function deepFullCopyDeparted(obj, deep = true) {
  //如果obj不是对象，那么直接返回值就可以了
  if (obj === null || obj === undefined || typeof obj !== "object") {
    return obj;
  }
  const utilDeepCopy = _u();
  //定义需要的局部变脸，根据 obj 的类型来调整 target 的类型
  let i;
  const target = utilDeepCopy.isType(obj, "array") ? [] : {};
  let value;
  let valueType;
  for (i in obj) {
    value = obj[i];
    valueType = utilDeepCopy.getType(value);
    //只有在明确执行深复制，并且当前的value是数组或对象的情况下才执行递归复制
    if (deep && (valueType === "array" || valueType === "object")) {
      target[i] = deepFullCopy(value);
    } else {
      target[i] = value;
    }
  }
  return target;

  function _u() {
    const class2type = {};
    [
      "Null",
      "Undefined",
      "Number",
      "Boolean",
      "String",
      "Object",
      "Function",
      "Array",
      "RegExp",
      "Date",
    ].forEach(function (item) {
      class2type[`[object ${item}]`] = item.toLowerCase();
    });

    function isType(obj, type) {
      return getType(obj) === type;
    }

    function getType(obj) {
      return class2type[Object.prototype.toString.call(obj)] || "object";
    }

    return {
      isType: isType,
      getType: getType,
    };
  }
}

//对象列表，通过对象唯一属性，去掉重复的项目：conditionValue
export function uniquelizeArray(t, index) {
  const tmp = {};
  const ret = [];
  for (let i = 0, j = t.length; i < j; i++) {
    if (!tmp[t[i][index]]) {
      tmp[t[i][index]] = 1;
      ret.push(t[i]);
    }
  }
  return ret;
}

/**
 * 节流函数,一般用户输入框
 * @fn function
 * @delay number
 * @mustRunDelay number
 * @return function
 */
export function superThrottle(fn, delay, mustRunDelay) {
  let timer = null;
  let tStart;
  return function () {
    const context = this;
    const args = arguments;
    const tCurr = +new Date();
    clearTimeout(timer);
    if (!tStart) {
      tStart = tCurr;
    }
    if (tCurr - tStart >= mustRunDelay) {
      fn.apply(context, args);
      tStart = tCurr;
    } else {
      timer = setTimeout(function () {
        fn.apply(context, args);
      }, delay);
    }
  };
}

/**
 * 对象数组去重(数组元素是对象)
 * @param arr
 * @key 以key去重 [{key:1},{key:1}]
 * @return 目标数组
 */
export function uniqueObjArr(arr, key) {
  const _arr = arr.map((item) => {
    return item[key];
  });
  const uArr = uniqueArr(_arr);
  return uArr.map((item) => {
    return findObj(item, arr, key);
  });

  function findObj(val, arr, key) {
    for (let i = 0; i < arr.length; i++) {
      if (arr[i][key] === val) {
        return arr[i];
      }
    }
  }
}

/**
 * 数组去重
 * @param arr
 * @return 目标数组
 */
export function uniqueArr(arr) {
  if (whatType(arr) === "array") {
    const res = [];
    for (let i = 0; i < arr.length; i++) {
      if (res.indexOf(arr[i]) === -1) {
        res.push(arr[i]);
      }
    }
    return res;
  }
  //抛错，但是不想抛错，js允许容错
  console.log("不是数组");
}

/*
 * 判断类型
 * @arg
 * @return jstype
 * */
export function whatType(arg) {
  let type = false;
  try {
    type = Object.prototype.toString.call(arg);
    type = type.slice(8, type.length - 1).toLowerCase();
  } catch (e) {
    //无法识别参数类型
    console.log(e);
  }
  return type;
}

/**
 * 去掉前后空格
 * @str string
 * @return string
 */
export function trim(str) {
  if (whatType(str) === "string") {
    return str.replace(/^(\s|\u00A0)+/, "").replace(/(\s|\u00A0)+$/, "");
  }
}

/**
 * 转换对象为url query参数
 * @param params
 * @return string
 */
export function paramsParse(params) {
  let str = "?";
  for (const key in params) {
    str += key;
    str += "=";
    str += params[key];
    str += "&";
  }
  return str.substring(0, str.length - 1);
}

/**
 * 检测是否为空对象
 * @param obj
 * @return bool
 */
export function isEmptyObj(obj) {
  for (const name in obj) {
    return false;
  }
  return true;
}

//获取当前时间
export function getTime() {
  return new Date().getTime();
}

/**
 * 从url中获取参数
 * @url string
 * @return obj 使用new方式获取url对象
 */
export function getUrlSearchParams(url) {
  return new UrlSearch(url);

  function UrlSearch(url) {
    let name;
    let value;
    let str;
    let num;
    str = url || window.location.href; //取得整个地址栏
    num = str.indexOf("?");
    str = str.substr(num + 1); //取得所有参数   stringvar.substr(start [, length ]
    const arr = str.split("&"); //各个参数放到数组里
    for (let i = 0; i < arr.length; i++) {
      num = arr[i].indexOf("=");
      if (num > 0) {
        name = arr[i].substring(0, num);
        value = arr[i].substr(num + 1);
        this[name] = value;
      }
    }
  }
}

/**
 * 超过一定限制的字符就截取
 * @param length 开始截取的长度
 * @param string 字符串
 * @return obj 返回的对象，包含源字符串与截取后的
 */
export function fitText(string, length) {
  const obj = {
    origin: string,
    text: false,
  };
  if (string === "" || string === null || string === undefined) {
    return obj;
  }
  if (string && string.length > length) {
    obj.text = string.substr(0, length);
    obj.text += "...";
  }
  return obj;
}

/**
 * 超过一定限制的字符就截取
 * @param length 开始截取的长度
 * @param string 字符串
 * @return obj 返回截取的
 */
export function getSubText(string, length) {
  let str = string;
  if (string.length > length) {
    str =
      Object.prototype.toString.call(string) === "[object String]"
        ? string.substr(0, length)
        : string;
  }
  return str;
}

/**
 * 简化的国际化方法
 * @param id
 * @param values
 * @return string
 */
export function messages(id, values = {}, language) {
  if (!configureStore.store.getState)
    //如果没有store，初始化
    configureStore.reduxStore();
  let result = configureStore.store.getState().main.language.messages[id];
  if (language && language === "en") {
    result = en[id];
  }
  if (language && language === "zh") {
    result = zh[id];
  }
  //#代表没找到
  if (result === undefined) {
    return "#";
  }
  //匹配 {*} 格式
  result = result.replace(/\{(.*?)\}/g, (target, $1) => {
    let replacement = false;
    //values内寻找是否有值，否则不替换
    Object.keys(values).map((key) => {
      if (key === $1) replacement = values[key];
    });
    return replacement === undefined ? target : replacement;
  });
  return result;
}

/**
 * 产生随机 id
 * @param length 长度
 * @return obj 字符串
 */
export function randomString(length) {
  let id = "";
  const chars =
    "ABCDEFGHiJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
  for (let i = 0; i < length; i++) {
    id += chars.charAt(Math.floor(Math.random() * 60));
  }
  return id;
}

/**
 *用于生成uuid
 */
export function randomUUIDString() {
  return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}

//

/**
 * 根据语言代码获取语言名称
 * @param code 语言国际化代码，zh_cn,en等
 * @param languageList 多语言列表,后端返回的
 * @return name 字符串
 */
export function getLanguageName(code, languageList) {
  if (code) {
    let name = "";
    languageList.map((item) => {
      if (code.toLowerCase() === item.code.toLowerCase()) {
        name = item.comments;
      }
    });
    return name;
  }
  return "简体中文";
}

/**
 * 获取浏览器名称与版本,针对主流浏览器，详细给出名称
 * @return browserName 浏览器名称
 */
export function getBrowserInfo() {
  const { userAgent } = window.navigator; //取得浏览器的userAgent字符串
  const isOpera = userAgent.indexOf("Opera") > -1;
  const re = {
    name: window.navigator.appName,
    version: parseFloat(window.navigator.appVersion),
  };
  if (isOpera) {
    ////判断是否Opera浏览器
    re.name = "Opera";
    return re;
  }
  if (userAgent.indexOf("Firefox") > -1) {
    //判断是否Firefox浏览器
    re.name = "Firefox";
    return re;
  }
  if (userAgent.indexOf("Chrome") > -1) {
    //判断是否Chrome浏览器
    re.name = "Chrome";
    return re;
  }
  if (userAgent.indexOf("Safari") > -1) {
    //判断是否Safari浏览器
    re.name = "Safari";
    return re;
  }
  if (
    userAgent.indexOf("compatible") > -1 &&
    userAgent.indexOf("MSIE") > -1 &&
    !isOpera
  ) {
    re.name = "IE";
    return re;
  }
  return re;
}

// 格式化数字
export function formatNumber(val = 0) {
  let nerVal = "";
  const valStr = `${val}`.split(".");

  function cf(val) {
    return val.replace(/(\d)(?=(?:\d{3})+$)/g, "$1,");
  }

  // val 带小数点
  if (valStr.length === 2) {
    nerVal = `${cf(valStr[0])}.${valStr[1]}`;
  } else {
    nerVal = cf(valStr[0]);
  }
  return nerVal;
}

//删除数组对象
export function removeArryItem(arr, obj) {
  const index = arr.indexOf(obj);
  if (~index) {
    arr.splice(index, 1);
  }
}

//设置单点登录的 loading
export function isShowSSOLogining(url) {
  // let selfUrls = [
  //   "stage.huilianyi.com",
  //   "stage9084.huilianyi.com",
  //   "console.huilianyi.com",
  //   "console-my.huilianyi.com",
  //   "console-tc.huilianyi.com",
  // ];
  const cUrl = url || window.location.host;
  const cUrlArr = cUrl.split(".");
  const request = new getUrlSearchParams();
  if (cUrlArr[1] === "huilianyi" && cUrlArr[2] === "com") {
    if (
      cUrlArr[0].match(/^console/) ||
      cUrlArr[0].match(/^stage/) ||
      cUrlArr[0].match(/^uat/)
    ) {
      // 不显示loading
      // 是自己公版部署的
      return false;
    }
    if (request.loginType) {
      // 是私有化部署、单点登录配置
      return true;
    }
    return false;
  }
  //是各种ip 不显示loading
  return false;
}

//金额变动
export function invoiceAmountChange(isChange, amount, currencyCode) {
  const _this = React.Component.prototype;
  if (isChange) {
    return (
      <span className="money-cell" style={{ color: "#FD9828" }}>
        {messages("common.change")}{" "}
        {_this.filterMoney(amount, queryCurrencyPrecision(currencyCode), true)}
      </span>
    );
  }
  return _this.filterMoney(amount, queryCurrencyPrecision(currencyCode));
}

//获取审批历史
export function getApprovelHistory(id) {
  return constants.approvelHistory.filter((item) => item.id === id)[0] || {};
}

//处理列表标签
export function dealListTag(record) {
  const result = [];
  if (record.warningList) {
    const warningList = JSON.parse(record.warningList);
    warningList &&
      warningList[0] &&
      warningList // 按type排序
        .sort((a, b) => {
          return b.type - a.type;
        });
    warningList.map((item) => {
      let type = "";
      if (Number(item.type) === 1) {
        //强管控
        type = "error";
      }
      if (Number(item.type) === 0) {
        //弱管控
        type = "warning";
      }
      if (item.showFlag && item.title) {
        result.push(
          _renderExpandedRow(messages("common.label"), item.title, type)
        );
      }
    });
  }
  if (record.printFree) {
    result.push(
      _renderExpandedRow(
        messages("common.print.free"),
        messages("common.print.require")
      )
    );
  }
  if (record.noticeFlag) {
    result.push(
      _renderExpandedRow(
        messages("components.key190" /*财务通知*/),
        messages("components.key191" /*请进入 单据详情-审批历史 查看*/)
      )
    );
  }
  if (result.length > 0) {
    return result;
  }
  return null;

  function _renderExpandedRow(title, content, type) {
    return (
      <div
        style={{
          color:
            type === "error"
              ? "#FA6478"
              : type === "warning"
              ? "#1E78C8"
              : "rgba(0, 0, 0, 0.65)",
        }}
      >
        <span>{title}</span>
        {content && <span>：{content}</span>}
      </div>
    );
  }
}

/*计算方法，防止浮点数*/
export function addCalculate(a, b) {
  let c;
  let d;
  let e;
  try {
    c = a.toString().split(".")[1].length;
  } catch (f) {
    c = 0;
  }
  try {
    d = b.toString().split(".")[1].length;
  } catch (f) {
    d = 0;
  }
  return (
    (e = Math.pow(10, Math.max(c, d))),
    (mulCalculate(a, e) + mulCalculate(b, e)) / e
  );
}

export function subCalculate(a, b) {
  let c;
  let d;
  let e;
  try {
    c = a.toString().split(".")[1].length;
  } catch (f) {
    c = 0;
  }
  try {
    d = b.toString().split(".")[1].length;
  } catch (f) {
    d = 0;
  }
  return (
    (e = Math.pow(10, Math.max(c, d))),
    (mulCalculate(a, e) - mulCalculate(b, e)) / e
  );
}

export function mulCalculate(a, b) {
  let c = 0;
  const d = a.toString();
  const e = b.toString();
  try {
    c += d.split(".")[1].length;
  } catch (f) {}
  try {
    c += e.split(".")[1].length;
  } catch (f) {}
  return (
    (Number(d.replace(".", "")) * Number(e.replace(".", ""))) / Math.pow(10, c)
  );
}

//获取URL问号后面参数
export function getQueryUrlParam(name) {
  const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`, "i");
  const { href } = window.location;
  const r = href.substr(href.toString().indexOf("?") + 1).match(reg);
  if (r !== null) {
    return unescape(r[2]);
  }
  return "";
}

//处理筛选缓存数据
export function dealCache(searchForm, resultValues) {
  searchForm.map((search) => {
    if (search.type === "items") {
      search.items.map((item) => {
        resultValues[`${item.id}Lable`] = resultValues[item.id];
        item.defaultValue = resultValues[`${item.id}Lable`];
        if (
          (item.id === "beginDate" ||
            item.id === "endDate" ||
            item.id === "startDate" ||
            item.id === "submittedDateStart" ||
            item.id === "submittedDateEnd") &&
          item.defaultValue
        ) {
          item.defaultValue = moment(item.defaultValue);
        }
      });
    } else if (search.type === "list" || search.type === "searcher") {
      search.defaultValue = resultValues[`${search.id}ShowValue`];
    } else {
      search.defaultValue = resultValues[`${search.id}`];
      if (resultValues[`${search.id}Expand`])
        search[`${search.id}Expand`] = resultValues[`${search.id}Expand`];
      if (resultValues[`${search.id}Option`])
        search.options = resultValues[`${search.id}Option`];
    }
  });
  searchForm.expand = resultValues.expand;
}

//银行卡加密
export function bankAccountNoEncryption(value) {
  if (value && value.length > 8) {
    const reg = /^(\d{4})\d+(\d{4})$/;
    const encryptionNumber = value.length - 8;
    return value.replace(reg, `$1${"*".repeat(encryptionNumber)}$2`);
  }
  return value;
}

export function getToken() {
  return (
    sessionStorage.getItem("hly.token") || localStorage.getItem("hly.token")
  );
}

export function removeToken(language) {
  sessionStorage.getItem("hly.token") && sessionStorage.removeItem("hly.token");
  localStorage.getItem("hly.token") && localStorage.removeItem("hly.token");
  language &&
    localStorage.getItem("hly.language") &&
    localStorage.removeItem("hly.language");
}

/*
 * currencyCode:币种
 * money:金额
 * */
export function currencyPrecisionCal(currencyCode, money) {
  if (!currencyCode) {
    currencyCode = configureStore.store.getState().login.company.baseCurrency;
  }
  const precision = queryCurrencyPrecision(currencyCode);
  if (typeof money === "number") {
    return money.toFixed(precision);
  }
  if (money) {
    return Number(money).toFixed(precision);
  }
  return "";
}

/*
 *currencyCode:币种
 * */
export function queryCurrencyPrecision(currencyCode) {
  if (!currencyCode) {
    currencyCode = configureStore.store.getState().login.company.baseCurrency;
  }
  const { allCurrency } = configureStore.store.getState().cache;
  for (let i = 0; i < allCurrency.length; i++) {
    if (allCurrency[i].currencyCode === currencyCode) {
      return allCurrency[i].precision;
    }
  }
  return 2;
}

/**
 * 菜单排序
 * @param menu 路由菜单列表
 * @param config 排序后的菜单key数组 ["key1","key2"]
 * @return array 排序后的菜单列表
 */
export function sortMenu(menu, config) {
  if (config && config.length) {
    const sortMenu = [];
    config.map((item) => {
      menu.map((menuItem) => {
        if (menuItem.key === item) {
          sortMenu.push(menuItem);
        }
      });
    });
    menu.map((menuItem) => {
      if (config.indexOf(menuItem.key) === -1) {
        sortMenu.push(menuItem); //新加入的菜单，排序配置里还没有，放在最后
      }
    });
    return sortMenu;
  }
  return menu;
}

/**
 * 获取指定cookie值
 * @param cname 要获取的cookie字段名
 */
export function getCookie(cname) {
  const cookies = document.cookie.split(";");
  let cvalue = null;
  cookies.map((item) => {
    if (item.trim().indexOf(`${cname}=`) === 0)
      cvalue = JSON.parse(decodeURI(item.split("=")[1]));
  });
  return cvalue;
}

/**
 * 校验数字叫字母的编码
 * @param value  用校验的值
 * @param length  校验长度
 * @return bool
 */
export function validCode(value, length) {
  if (value === null || value === undefined || value === "") {
    return false;
  }
  let _length = 100;
  if (length) {
    _length = length;
  }
  const regExp = /^[a-z0-9_ ]+$/i;
  //去掉空格
  value = value.replace(/ /g, "");
  if (value.length <= _length && regExp.test(value)) {
    return true;
  }
  return false;
}

window.isSafari = navigator.userAgent.indexOf("Safari") > -1;
window.ISIE9 = navigator.appVersion.indexOf("MSIE 9.0") > -1;
window.ISIE = navigator.appVersion.indexOf("MSIE") > -1;

export function setLocalStorage(key, value) {
  try {
    localStorage.setItem(key, value);
  } catch (e) {
    if (isQuotaExceeded(e)) {
      alert(
        messages(
          messages(
            "components.key825"
          ) /*浏览器存储空间已满，请清理浏览器缓存或更换浏览器后再试*/
        )
      );
    }
  }

  function isQuotaExceeded(e) {
    let quotaExceeded = false;
    if (e) {
      if (e.code) {
        switch (e.code) {
          case 22:
            quotaExceeded = true;
            break;
          case 1014:
            // Firefox
            if (e.name === "NS_ERROR_DOM_QUOTA_REACHED") {
              quotaExceeded = true;
            }
            break;
        }
      } else if (e.number === -2147024882) {
        // Internet Explorer 8
        quotaExceeded = true;
      }
    }
    return quotaExceeded;
  }
}

//返回一个账套列表
//isOnlyCache是否只返回redux里的数据，不额外调接口，为false时会多返回一个租户下帐套列表
export function getDefaultSetOfBook(isOnlyCache) {
  const loginSetOfBook = {
    setOfBooksId: configureStore.store.getState().login.company.setOfBooksId,
    setOfBooksName: configureStore.store.getState().login.company
      .setOfBooksName,
  };
  const setOfBook = configureStore.store.getState().cache.defaultSetOfBook;
  const url = "/api/setOfBooks/by/tenant";
  if (isOnlyCache) {
    return JSON.parse(JSON.stringify(setOfBook));
  }
  return httpFetch.get(`${config.baseUrl}${url}`).then((res) => {
    return new Promise((resolve) => {
      if (res.data) {
        const result = JSON.parse(JSON.stringify(res));
        result.data.defaultSetOfBooksId = loginSetOfBook.setOfBooksId;
        result.data.defaultSetOfBooksName = loginSetOfBook.setOfBooksName;
        let isHasSetOfBooksId = false;
        result.data &&
          result.data.map((item) => {
            if (
              setOfBook &&
              setOfBook.setOfBooksId &&
              item.id === setOfBook.setOfBooksId
            ) {
              isHasSetOfBooksId = true;
            }
          });
        if (isHasSetOfBooksId) {
          result.data.defaultSetOfBooksId = setOfBook.setOfBooksId;
          result.data.defaultSetOfBooksName = setOfBook.setOfBooksName;
          Object.keys(setOfBook || {}).map((key) => {
            result.data[key] = setOfBook[key];
          });
        }
        resolve(result);
      } else {
        resolve(res);
      }
    });
  });
}

export function getSearchForm(params) {
  const searchForm = [];
  params.map((param) => {
    switch (param.type) {
      case "String":
        searchForm.push({
          type: "input",
          id: param.name,
          label: param.label,
          defaultValue: param.defaultValue,
        });
        break;
      case "DataSource":
        const source = param.dataSource;
        if (param.dataSource.paging) {
          const selectorItem = {
            title: param.label,
            url: source.url,
            searchForm: getSearchForm(source.searchParams),
            columns: source.keys,
            key: source.mainKey,
          };
          searchForm.push({
            type: "list",
            id: param.name,
            label: param.label,
            selectorItem,
            labelKey: param.labelKey,
            descriptionKey: param.descriptionKey,
            valueKey: source.mainKey,
            listExtraParams: source.params,
          });
        } else if (param.single) {
          const selectorItem = {
            url: source.url,
            label: param.labelKey,
            key: source.mainKey,
            showSearch: true,
            offlineSearchMode: true,
          };
          if (
            source.searchParams.length === 1 &&
            source.searchParams[0].type === "String"
          ) {
            selectorItem.offlineSearchMode = false;
            selectorItem.searchKey = source.searchParams[0].name;
          }
          searchForm.push({
            type: "selector",
            id: param.name,
            entity: true,
            labelKey: param.labelKey,
            label: param.label,
            selectorItem,
            params: source.params,
          });
        } else {
          const searcherItem = {
            title: param.label,
            url: source.url,
            key: source.mainKey,
          };
          searchForm.push({
            type: "searcher",
            id: param.name,
            label: param.label,
            searcherItem,
            labelKey: param.labelKey,
            descriptionKey: param.descriptionKey,
            valueKey: source.mainKey,
            listExtraParams: source.params,
          });
        }
        break;
      case "DateRange":
        const names = param.name.split(",");
        const labels = param.label.split(",");
        searchForm.push({
          type: "items",
          id: "dateRange",
          items: [
            { type: "date", id: names[0], label: labels[0] },
            { type: "date", id: names[1], label: labels[1] },
          ],
        });
    }
  });
  return searchForm;
}

//进入某个页面时按需引入当前页面所需的script, scriptSrc为需要引入的script路径
export function loadScript(scriptSrc) {
  return new Promise((resolve, reject) => {
    const script = document.createElement("script");
    script.type = "text/javascript";
    script.src = scriptSrc;
    try {
      script.appendChild(document.createTextNode("//code")); //javascript内容是利用createTextNode创建的（不过IE不认这个）
    } catch (e) {
      script.text = "//code"; //IE认为SCRIPT节点是个特殊的节点所有有个特殊的text属性
    }
    document.body.appendChild(script); /*兼容IE*/
    script.onload = () => {
      resolve();
    };
    script.onerror = () => {
      reject();
    };
  });
}

// 信用分处理
export function handleHonest(value) {
  const honestMap = new Map([
    [
      1001,
      { sign: messages("components.key741") /*加分*/, type: "changeScore" },
    ],
    [
      1002,
      { sign: messages("components.key742") /*减分*/, type: "changeScore" },
    ],
    [
      1003,
      { sign: messages("components.key743") /*升级*/, type: "changeRank" },
    ],
    [
      1004,
      { sign: messages("components.key744") /*降级*/, type: "changeRank" },
    ],
  ]);
  const temp = honestMap.get(value.operationType);
  return `${temp.sign} ${value[temp.type]}`;
}

/**
 * MD5加密方法 从hongkong脚本里拿来的 腾讯地图请求时校验密钥用
 * */
export function MD5(string) {
  function RotateLeft(lValue, iShiftBits) {
    return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
  }

  function AddUnsigned(lX, lY) {
    let lX4;
    let lY4;
    let lX8;
    let lY8;
    let lResult;
    lX8 = lX & 0x80000000;
    lY8 = lY & 0x80000000;
    lX4 = lX & 0x40000000;
    lY4 = lY & 0x40000000;
    lResult = (lX & 0x3fffffff) + (lY & 0x3fffffff);
    if (lX4 & lY4) {
      return lResult ^ 0x80000000 ^ lX8 ^ lY8;
    }
    if (lX4 | lY4) {
      if (lResult & 0x40000000) {
        return lResult ^ 0xc0000000 ^ lX8 ^ lY8;
      }
      return lResult ^ 0x40000000 ^ lX8 ^ lY8;
    }
    return lResult ^ lX8 ^ lY8;
  }

  function F(x, y, z) {
    return (x & y) | (~x & z);
  }

  function G(x, y, z) {
    return (x & z) | (y & ~z);
  }

  function H(x, y, z) {
    return x ^ y ^ z;
  }

  function I(x, y, z) {
    return y ^ (x | ~z);
  }

  function FF(a, b, c, d, x, s, ac) {
    a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
    return AddUnsigned(RotateLeft(a, s), b);
  }

  function GG(a, b, c, d, x, s, ac) {
    a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
    return AddUnsigned(RotateLeft(a, s), b);
  }

  function HH(a, b, c, d, x, s, ac) {
    a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
    return AddUnsigned(RotateLeft(a, s), b);
  }

  function II(a, b, c, d, x, s, ac) {
    a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
    return AddUnsigned(RotateLeft(a, s), b);
  }

  function ConvertToWordArray(string) {
    let lWordCount;
    const lMessageLength = string.length;
    const lNumberOfWords_temp1 = lMessageLength + 8;
    const lNumberOfWords_temp2 =
      (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
    const lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
    const lWordArray = Array(lNumberOfWords - 1);
    let lBytePosition = 0;
    let lByteCount = 0;
    while (lByteCount < lMessageLength) {
      lWordCount = (lByteCount - (lByteCount % 4)) / 4;
      lBytePosition = (lByteCount % 4) * 8;
      lWordArray[lWordCount] =
        lWordArray[lWordCount] |
        (string.charCodeAt(lByteCount) << lBytePosition);
      lByteCount++;
    }
    lWordCount = (lByteCount - (lByteCount % 4)) / 4;
    lBytePosition = (lByteCount % 4) * 8;
    lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
    lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
    lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
    return lWordArray;
  }

  function WordToHex(lValue) {
    let WordToHexValue = "";
    let WordToHexValue_temp = "";
    let lByte;

    let lCount;
    for (lCount = 0; lCount <= 3; lCount++) {
      lByte = (lValue >>> (lCount * 8)) & 255;
      WordToHexValue_temp = `0${lByte.toString(16)}`;
      WordToHexValue += WordToHexValue_temp.substr(
        WordToHexValue_temp.length - 2,
        2
      );
    }
    return WordToHexValue;
  }

  function Utf8Encode(string) {
    string = string.replace(/\r\n/g, "\n");
    let utftext = "";

    for (let n = 0; n < string.length; n++) {
      const c = string.charCodeAt(n);

      if (c < 128) {
        utftext += String.fromCharCode(c);
      } else if (c > 127 && c < 2048) {
        utftext += String.fromCharCode((c >> 6) | 192);
        utftext += String.fromCharCode((c & 63) | 128);
      } else {
        utftext += String.fromCharCode((c >> 12) | 224);
        utftext += String.fromCharCode(((c >> 6) & 63) | 128);
        utftext += String.fromCharCode((c & 63) | 128);
      }
    }

    return utftext;
  }

  let x = Array();
  let k;
  let AA;
  let BB;
  let CC;
  let DD;
  let a;
  let b;
  let c;
  let d;
  const S11 = 7;
  const S12 = 12;
  const S13 = 17;

  const S14 = 22;
  const S21 = 5;
  const S22 = 9;
  const S23 = 14;

  const S24 = 20;
  const S31 = 4;
  const S32 = 11;
  const S33 = 16;

  const S34 = 23;
  const S41 = 6;
  const S42 = 10;
  const S43 = 15;

  const S44 = 21;

  string = Utf8Encode(string);

  x = ConvertToWordArray(string);

  a = 0x67452301;
  b = 0xefcdab89;
  c = 0x98badcfe;
  d = 0x10325476;

  for (k = 0; k < x.length; k += 16) {
    AA = a;
    BB = b;
    CC = c;
    DD = d;
    a = FF(a, b, c, d, x[k + 0], S11, 0xd76aa478);
    d = FF(d, a, b, c, x[k + 1], S12, 0xe8c7b756);
    c = FF(c, d, a, b, x[k + 2], S13, 0x242070db);
    b = FF(b, c, d, a, x[k + 3], S14, 0xc1bdceee);
    a = FF(a, b, c, d, x[k + 4], S11, 0xf57c0faf);
    d = FF(d, a, b, c, x[k + 5], S12, 0x4787c62a);
    c = FF(c, d, a, b, x[k + 6], S13, 0xa8304613);
    b = FF(b, c, d, a, x[k + 7], S14, 0xfd469501);
    a = FF(a, b, c, d, x[k + 8], S11, 0x698098d8);
    d = FF(d, a, b, c, x[k + 9], S12, 0x8b44f7af);
    c = FF(c, d, a, b, x[k + 10], S13, 0xffff5bb1);
    b = FF(b, c, d, a, x[k + 11], S14, 0x895cd7be);
    a = FF(a, b, c, d, x[k + 12], S11, 0x6b901122);
    d = FF(d, a, b, c, x[k + 13], S12, 0xfd987193);
    c = FF(c, d, a, b, x[k + 14], S13, 0xa679438e);
    b = FF(b, c, d, a, x[k + 15], S14, 0x49b40821);
    a = GG(a, b, c, d, x[k + 1], S21, 0xf61e2562);
    d = GG(d, a, b, c, x[k + 6], S22, 0xc040b340);
    c = GG(c, d, a, b, x[k + 11], S23, 0x265e5a51);
    b = GG(b, c, d, a, x[k + 0], S24, 0xe9b6c7aa);
    a = GG(a, b, c, d, x[k + 5], S21, 0xd62f105d);
    d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
    c = GG(c, d, a, b, x[k + 15], S23, 0xd8a1e681);
    b = GG(b, c, d, a, x[k + 4], S24, 0xe7d3fbc8);
    a = GG(a, b, c, d, x[k + 9], S21, 0x21e1cde6);
    d = GG(d, a, b, c, x[k + 14], S22, 0xc33707d6);
    c = GG(c, d, a, b, x[k + 3], S23, 0xf4d50d87);
    b = GG(b, c, d, a, x[k + 8], S24, 0x455a14ed);
    a = GG(a, b, c, d, x[k + 13], S21, 0xa9e3e905);
    d = GG(d, a, b, c, x[k + 2], S22, 0xfcefa3f8);
    c = GG(c, d, a, b, x[k + 7], S23, 0x676f02d9);
    b = GG(b, c, d, a, x[k + 12], S24, 0x8d2a4c8a);
    a = HH(a, b, c, d, x[k + 5], S31, 0xfffa3942);
    d = HH(d, a, b, c, x[k + 8], S32, 0x8771f681);
    c = HH(c, d, a, b, x[k + 11], S33, 0x6d9d6122);
    b = HH(b, c, d, a, x[k + 14], S34, 0xfde5380c);
    a = HH(a, b, c, d, x[k + 1], S31, 0xa4beea44);
    d = HH(d, a, b, c, x[k + 4], S32, 0x4bdecfa9);
    c = HH(c, d, a, b, x[k + 7], S33, 0xf6bb4b60);
    b = HH(b, c, d, a, x[k + 10], S34, 0xbebfbc70);
    a = HH(a, b, c, d, x[k + 13], S31, 0x289b7ec6);
    d = HH(d, a, b, c, x[k + 0], S32, 0xeaa127fa);
    c = HH(c, d, a, b, x[k + 3], S33, 0xd4ef3085);
    b = HH(b, c, d, a, x[k + 6], S34, 0x4881d05);
    a = HH(a, b, c, d, x[k + 9], S31, 0xd9d4d039);
    d = HH(d, a, b, c, x[k + 12], S32, 0xe6db99e5);
    c = HH(c, d, a, b, x[k + 15], S33, 0x1fa27cf8);
    b = HH(b, c, d, a, x[k + 2], S34, 0xc4ac5665);
    a = II(a, b, c, d, x[k + 0], S41, 0xf4292244);
    d = II(d, a, b, c, x[k + 7], S42, 0x432aff97);
    c = II(c, d, a, b, x[k + 14], S43, 0xab9423a7);
    b = II(b, c, d, a, x[k + 5], S44, 0xfc93a039);
    a = II(a, b, c, d, x[k + 12], S41, 0x655b59c3);
    d = II(d, a, b, c, x[k + 3], S42, 0x8f0ccc92);
    c = II(c, d, a, b, x[k + 10], S43, 0xffeff47d);
    b = II(b, c, d, a, x[k + 1], S44, 0x85845dd1);
    a = II(a, b, c, d, x[k + 8], S41, 0x6fa87e4f);
    d = II(d, a, b, c, x[k + 15], S42, 0xfe2ce6e0);
    c = II(c, d, a, b, x[k + 6], S43, 0xa3014314);
    b = II(b, c, d, a, x[k + 13], S44, 0x4e0811a1);
    a = II(a, b, c, d, x[k + 4], S41, 0xf7537e82);
    d = II(d, a, b, c, x[k + 11], S42, 0xbd3af235);
    c = II(c, d, a, b, x[k + 2], S43, 0x2ad7d2bb);
    b = II(b, c, d, a, x[k + 9], S44, 0xeb86d391);
    a = AddUnsigned(a, AA);
    b = AddUnsigned(b, BB);
    c = AddUnsigned(c, CC);
    d = AddUnsigned(d, DD);
  }

  const temp = WordToHex(a) + WordToHex(b) + WordToHex(c) + WordToHex(d);

  return temp.toLowerCase();
}

export const EventUtils = {
  addHandler(el, type, handler, capture = false) {
    if (el.addEventListener) {
      el.addEventListener(type, handler, capture);
    } else if (el.attachEvent) {
      el.attachEvent(`on${type}`, handler);
    } else {
      el[`on${type}`] = handler;
    }
  },
  removeHandler(el, type, handler) {
    if (el.removeEventListener) {
      el.removeEventListener(type, handler);
    } else if (el.detachEvent) {
      el.detachEvent(`on${type}`, handler);
    } else {
      el[`on${type}`] = null;
    }
  },
  getTarget($e) {
    return $e.target || $e.srcElement;
  },
  preventDefault($e) {
    $e.preventDefault ? $e.preventDefault() : ($e.returnValue = false);
  },
  stopPropagation($e) {
    $e.stopPropagation ? $e.stopPropagation() : ($e.cancelBubble = true);
  },
};

/**
 * lodash.flow
 * @param funcs 要调用的函数
 * @returns {function(...[*]=): *}
 */
export function flow(...funcs) {
  const length = funcs ? funcs.length : 0;
  let index = length;
  while (index--) {
    if (typeof funcs[index] != "function") {
      throw new TypeError("Expected a function");
    }
  }
  return function (...args) {
    let index = 0;
    let result = length ? funcs[index].apply(this, args) : args[0];
    while (++index < length) {
      result = funcs[index].call(this, result);
    }
    return result;
  };
}

export function eventTrack(params) {
  // category 要监控的目标的类型名称 必填 action 用户跟网页进行交互的动作名称 必填 label 事件的一些额外信息
  if (Object.prototype.hasOwnProperty.call(window, "_hmt")) {
    window._hmt.push([
      "_trackEvent",
      params.category,
      params.action,
      params.label,
    ]);
  }
}

export function omit(obj, key) {
  const isArray = Array.isArray(key);
  if (obj) {
    return Object.keys(obj).reduce((left, right) => {
      const shouldOmit = isArray ? key.includes(right) : key === right;
      if (!shouldOmit) {
        left[right] = obj[right];
      }
      return left;
    }, {});
  }
}

//这是第一版。只检查当前菜单下的当前tab的operationType是否为R，R代表只读，无操作权限。key是当前tab的key
export function checkTabDisabled(key) {
  const currentMenu =
    configureStore.store.getState().main.currentMenuPermission.currentMenu ||
    {};
  if (currentMenu.subFunctions && currentMenu.subFunctions.length) {
    const arr = currentMenu.subFunctions.filter((item) => item.key === key);
    if (arr && arr.length) {
      return arr[0].operationType === "R";
    }
  }
}

/*
 * typeList: [authPolicyAll(全租户权限), setOfBook（账套权限）, company（公司权限）]
 * return 的 disabled 代表当前菜单下是否拥有typeList中的一个权限并且菜单操作属性不是只读（即operationType不为R）
 * */
export function checkMenuDisabled(
  typeList = ["authPolicyAll", "setOfBook", "company"]
) {
  const currentMenu =
    configureStore.store.getState().main.currentMenuPermission.currentMenu ||
    {};
  const readOnly = currentMenu.operationType === "R";
  let hasPermission = checkMenuPermission(typeList);
  return readOnly || !hasPermission;
}

/*
 * 按着上面代码同样的逻辑 加上 精细到按钮权限的判断，需要多给个字段  buttonKey （这个 buttonKey 需要和运营平台配置的一样）
 * */
export function checkButtonDisabled(buttonKey) {
  const currentMenu =
    configureStore.store.getState().main.currentMenuPermission.currentMenu ||
    {};
  let readOnly = currentMenu.operationType === "R";
  let buttonDisabled;
  if (currentMenu.buttons && currentMenu.buttons.length) {
    if (currentMenu.buttons.filter((item) => item.key === buttonKey).length) {
      buttonDisabled = false;
    } else {
      buttonDisabled = true;
    }
  } else {
    buttonDisabled = true;
  }
  return readOnly || buttonDisabled;
}

/*
 * 梁宏新出了一种要求。某菜单下的tab及其子路由，其disabled要受菜单的权限的管控和tab的operationType管控.key是tab的key。
 * typeList: [authPolicyAll(全租户权限), setOfBook（账套权限）, company（公司权限）]
 * 用法示例：let disabled = checkTabDisabledV2("custom-value-list", ["authPolicyAll", "setOfBook", "company"]);
 * custom-value-list是自定义值列表的tab的key；
 * ["authPolicyAll", "setOfBook", "company"]代表只要当前用户拥有这三者其中之一的菜单权限，他就拥有可操作权限。
 * 总而言之：tab只读或者没有权限，disabled就为true。
 * */
export function checkTabDisabledV2(
  key,
  typeList = ["authPolicyAll", "setOfBook", "company"]
) {
  const currentMenu =
    configureStore.store.getState().main.currentMenuPermission.currentMenu ||
    {};
  let readOnly = false;
  let hasPermission = checkMenuPermission(typeList);
  if (currentMenu.subFunctions && currentMenu.subFunctions.length) {
    const arr = currentMenu.subFunctions.filter((item) => item.key === key);
    if (arr && arr.length) {
      readOnly = arr[0].operationType === "R";
    }
  }
  return readOnly || !hasPermission;
}

export function checkMenuPermission(
  typeList = ["authPolicyAll", "setOfBook", "company"]
) {
  const menuPermission =
    configureStore.store.getState().main.menuPermission || {};
  let { authPolicyAll } = menuPermission;
  let setOfBook =
    menuPermission.authPolicyCompDTO &&
    menuPermission.authPolicyCompDTO.setOfBooksIds &&
    menuPermission.authPolicyCompDTO.setOfBooksIds.length;
  let company =
    menuPermission.authPolicyCompDTO &&
    menuPermission.authPolicyCompDTO.companyIds &&
    menuPermission.authPolicyCompDTO.companyIds.length;
  let obj = { authPolicyAll, setOfBook, company };
  let hasPermission = false;
  typeList.forEach((item) => {
    hasPermission = hasPermission || obj[item];
  });
  return hasPermission;
}

//获取新权限下的默认账套
export function getDefaultPermissionSetOfBook() {
  //默认登录人账套
  const loginSetOfBook = {
    defaultSetOfBooksId: configureStore.store.getState().login.company
      .setOfBooksId,
    defaultSetOfBooksName: configureStore.store.getState().login.company
      .setOfBooksName,
  };
  const url = "/api/setOfBooks/query/dto?enabled=true&page=0&size=9999";
  return httpFetch.get(`${config.baseUrl}${url}`).then((res) => {
    return new Promise((resolve) => {
      if (res && res.data) {
        if (!!res.data.length) {
          const result = {
            data: {
              // setOfBooks: res.data,
              defaultSetOfBooksId: res.data[0].setOfBooksId,
              defaultSetOfBooksName: res.data[0].setOfBooksName,
            },
          };
          (res.data || []).map((item) => {
            if (item.setOfBooksId === loginSetOfBook.defaultSetOfBooksId) {
              result.data.defaultSetOfBooksId =
                loginSetOfBook.defaultSetOfBooksId;
              result.data.defaultSetOfBooksName =
                loginSetOfBook.defaultSetOfBooksName;
            }
          });
          console.log(result);
          resolve(result);
        }
      } else {
        resolve(res);
      }
    });
  });
}

//获取新权限下的默认公司
export function getDefaultPermissionCompany() {
  //默认登录人公司
  console.log(configureStore.store.getState().login.company);
  const loginCompany = {
    companyOID: configureStore.store.getState().login.company.companyOID,
    name: configureStore.store.getState().login.company.companyName,
    setOfBooksId: configureStore.store.getState().login.company.setOfBooksId,
  };
  const url = "/api/widget/company/all?enabled=true";
  return httpFetch.get(`${config.baseUrl}${url}`).then((res) => {
    return new Promise((resolve) => {
      if (res && res.data) {
        if (res.data.length) {
          let result = {
            id: res.data[0].id,
            companyOID: res.data[0].companyOID,
            name: res.data[0].name,
            setOfBooksId: res.data[0].setOfBooksId,
          };
          (res.data || []).map((item) => {
            if (item.companyOID === loginCompany.companyOID) {
              result = {
                id: item.id,
                companyOID: item.companyOID,
                name: item.name,
                setOfBooksId: item.setOfBooksId,
              };
            }
          });
          resolve(result);
        }
      } else {
        resolve(res);
      }
    });
  });
}

export function simplifyDataSource(data, attr = "columns") {
  return data.map((item) => {
    const attrName = Object.getOwnPropertyNames(item);
    let key = attrName[0];
    let firstAttr = { title: item[key], dataIndex: key },
      obj = firstAttr;
    if (attrName.length > 1) {
      delete item[key];
      obj = Object.assign(firstAttr, item);
    }
    if (!item.render) {
      const renderObj = {
        attr: (text) => (text ? text : "-"),
        columns: (text) =>
          text ? (
            <Popover content={text}>{text ? text : "-"}</Popover>
          ) : text ? (
            text
          ) : (
            "-"
          ),
      };
      obj.render = renderObj[attr];
    }
    if (item.width) {
      obj.width = item.width;
    }
    return obj;
  });
}

export function getCamelCase(str) {
  const re = /-(\w)/g;
  return str.replace(re, function ($0, $1) {
    return $1.toUpperCase();
  });
}

export function dealRealmId(urlString) {
  function addRealId(url) {
    // let isDingTalkEnv = configureStore.store.getState().main.isDingTalkEnv;
    let isBydEnv = configureStore.store.getState().main.isBydEnv;
    let isTcEnv = configureStore.store.getState().main.isTcEnv;
    // if (isDingTalkEnv) {
    //   return addRealmId(url, '639518855899537002');
    // } else
    if (isBydEnv) {
      return addRealmId(url, "905692682284599319");
    }
    if (isTcEnv) {
      return addRealmId(url, "1005671681484599307");
    } else if (window.location.href.indexOf("console-dd.huilianyi.com") > -1) {
      // 新增钉钉realmID 2020 02 14
      return addRealmId(url, "639518855899537002");
    } else if (
      window.location.href.indexOf("console-welink.huilianyi.com") > -1
    ) {
      return addRealmId(url, "805692892184599332");
    }
    return url;
  }

  function addRealmId(url, realmId) {
    console.log("addrealmid-->", realmId);
    const { isTcEnv } = configureStore.store.getState().main;
    if (
      url.indexOf("/vendor-info-service") > -1 ||
      (url.indexOf("/vendor-data-service") > -1 && !isTcEnv) ||
      url.indexOf("/open") > -1
    ) {
      if (url.indexOf("?") > -1) {
        url += `&realmId=${realmId}`;
        /**uat: 739514855899537002   prod: 905692682284599319*/
      } else {
        url += `?realmId=${realmId}`;
      }
    }
    return url;
  }
  return addRealId(urlString);
}

/**
 * Todo: 只能对比两个标准对象的，需要扩充下
 * @param a
 * @param b
 * @returns {boolean}
 */
export function isObjectValueEqual(a, b) {
  let aKeys = Object.keys(a);
  let bKeys = Object.keys(b);
  if (aKeys.sort().toString() !== bKeys.sort().toString()) {
    return false;
  }
  let isEqual = true;
  aKeys.map((item) => {
    a[item] !== b[item] && (isEqual = false);
  });
  return isEqual;
}

export function handleExportError(data) {
  const result = [];
  if (data) {
    if (
      data.detailPage &&
      data.detailPage.content &&
      data.detailPage.content.length > 0
    ) {
      data.detailPage.content.forEach((i) => {
        i.index = i.lineNumber;
        i.error = i.errorMessage;
        result.push(i);
      });
    } else if (data && data.errors) {
      data &&
        Object.keys(data.errors).map((item) => {
          data.errors[item].forEach((subItem) => {
            const tempResult = {};
            tempResult.index = subItem;
            tempResult.error = item;
            result.push(tempResult);
          });
        });
    }
  }
  return result;
}

// 若本地无token
// 且链接有 state=feishu && feishuQRUrl  就重定向到 飞书扫码授权页面
export function judgeLarkUrl(needBack) {
  const query = window.location.search;
  const request = getUrlSearchParams();
  if (
    query.indexOf("state=feishu") !== -1 &&
    query.indexOf("feishuQRUrl=") !== -1
  ) {
    window.location.replace(decodeURIComponent(request.feishuQRUrl));
  } else if (needBack)
    //是否需要回到 /
    location.href = "/";
}

// 登录页 与 体验登录后  跳转 预约演示的页面 该方法 就是把 utm 相关字段带上了
export function goToAppointment(isOfficialWebsite) {
  const utmSourceData = localStorage.getItem("hly.utmSourceData");
  if (utmSourceData !== null) {
    const parseData = JSON.parse(utmSourceData);
    if (parseData.generateTimeStamp > Date.parse(new Date().toString())) {
      let query = "";
      Object.keys(parseData.utmKeyObject).forEach((item) => {
        query += `&${item}=${parseData.utmKeyObject[item]}`;
      });
      let url;
      if (isOfficialWebsite)
        url = `https://www.huilianyi.com/${query}`.replace("&", "?");
      else url = `https://www.huilianyi.com/trial2?type=rq${query}`;
      window.open(url, "_blank");
    } else {
      openOriginal();
    }
  } else {
    openOriginal();
  }
  function openOriginal() {
    let url;
    if (isOfficialWebsite) url = `https://www.huilianyi.com/`;
    else url = `https://www.huilianyi.com/trial2?type=rq`;
    window.open(url, "_blank");
  }
}

// 检测是否支持页面 js 操作 滚动。
export function isSupportScroll(ref) {
  if (ref && ref.scrollTo) {
    return true;
  }
  if (ref && ref.scrollTop) {
    return true;
  } else {
    return false;
  }
}

// 滚动到指定位置。 页面滚动这边 有两种方法  一个是 直接dom赋值scrollTop 一种是 调用 scrollTo 方法。
// 部分浏览器很奇怪 window 有 scrollTo方法，dom 没有。  所以 做兼容 就直接赋值 scrollTop
// 关于滚动是否是 动画滚动过去  这个 就要看 浏览器支持不支持  scroll behavior 了。 这儿我就不用 scrollTo({option})方法了
// 建议 直接在 css 里 加上 scroll-behavior: smooth;   即可。。 因为如果不支持  用 option 就 都不执行
export function scrollToMyDestination(ref, y) {
  if (ref && ref.scrollTo) {
    ref.scrollTo(0, y);
  } else if (ref && ref.scrollTop !== undefined) {
    ref.scrollTop = y;
  } else {
    return false;
  }
}

export function ignoreTimeZone(dateString) {
  if (typeof dateString !== "string") return dateString;
  if (dateString.endsWith("Z")) return dateString.slice(0, -1); //utc时间格式2020-05-07T23:59:00Z
  return dateString.split("+")[0]; //本地时间格式 2020-05-07T23:59:00+08:00
}

export function decodeUtf8(arrayBuffer) {
  let result = "";
  let i = 0;
  let c = 0;
  let c2 = 0;
  let c3 = 0;

  let data = new Uint8Array(arrayBuffer);

  // If we have a BOM skip it
  if (
    data.length >= 3 &&
    data[0] === 0xef &&
    data[1] === 0xbb &&
    data[2] === 0xbf
  ) {
    i = 3;
  }

  while (i < data.length) {
    c = data[i];

    if (c < 128) {
      result += String.fromCharCode(c);
      i++;
    } else if (c > 191 && c < 224) {
      if (i + 1 >= data.length) {
        throw "UTF-8 Decode failed. Two byte character was truncated.";
      }
      c2 = data[i + 1];
      result += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
      i += 2;
    } else {
      if (i + 2 >= data.length) {
        throw "UTF-8 Decode failed. Multi byte character was truncated.";
      }
      c2 = data[i + 1];
      c3 = data[i + 2];
      result += String.fromCharCode(
        ((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)
      );
      i += 3;
    }
  }
  return result;
}

export function urlMatch(param) {
  let bool = false;
  let { href } = window.location;
  if (typeof param === "string") {
    bool = href.indexOf(param) !== -1;
  } else if (param instanceof Array) {
    bool = param.some((item) => urlMatch(item));
  }
  return bool;
}

export function shallowEqual(props, nextProps) {
  if (props === nextProps) {
    return true;
  } else if (
    typeof props === "object" &&
    props !== null &&
    typeof nextProps === "object" &&
    nextProps !== null
  ) {
    if (Object.keys(props).length !== Object.keys(nextProps).length) {
      return false;
    } else {
      for (let temp in props) {
        if (nextProps.hasOwnProperty(temp)) {
          if (props[temp] !== nextProps[temp]) {
            return false;
          }
        } else {
          return false;
        }
      }
      return true;
    }
  } else {
    return false;
  }
}

